#include "triangularprism.h"
#include "triangle.h"
#include "rectangle.h"
#include <GL/gl.h>

TriangularPrism::TriangularPrism()
{
    vertices_.push_back(new Point(-1.0/3.0, -0.5, 2.0/3.0));
    vertices_.push_back(new Point(-1.0/3.0, -0.5, -1.0/3.0));
    vertices_.push_back(new Point(2.0/3.0, -0.5, -1.0/3.0));
    // bottom base
    Face bottom_base;
    bottom_base.push_back(new Edge(vertices_[0], vertices_[1]));
    bottom_base.push_back(new Edge(vertices_[1], vertices_[2]));
    bottom_base.push_back(new Edge(vertices_[2], vertices_[0]));
    faces_.push_back(bottom_base);

    // top base
    vertices_.push_back(new Point(-1.0/3.0, 0.5, 2.0/3.0));
    vertices_.push_back(new Point(-1.0/3.0, 0.5, -1.0/3.0));
    vertices_.push_back(new Point(2.0/3.0, 0.5, -1.0/3.0));
    edges_.push_back(new Edge(vertices_[3], vertices_[4]));
    edges_.push_back(new Edge(vertices_[4], vertices_[5]));
    edges_.push_back(new Edge(vertices_[5], vertices_[3]));
    Face top_base;
    top_base.push_back(new Edge(vertices_[3], vertices_[4]));
    top_base.push_back(new Edge(vertices_[4], vertices_[5]));
    top_base.push_back(new Edge(vertices_[5], vertices_[3]));
    faces_.push_back(top_base);

    // Lateral face 1
    Face lateral1;
    lateral1.push_back(new Edge(vertices_[1], vertices_[0]));
    lateral1.push_back(new Edge(vertices_[0], vertices_[3]));
    lateral1.push_back(new Edge(vertices_[3], vertices_[4]));
    lateral1.push_back(new Edge(vertices_[4], vertices_[1]));
    faces_.push_back(lateral1);

    // Lateral face 2
    Face lateral2;
    lateral2.push_back(new Edge(vertices_[2], vertices_[1]));
    lateral2.push_back(new Edge(vertices_[1], vertices_[4]));
    lateral2.push_back(new Edge(vertices_[4], vertices_[5]));
    lateral2.push_back(new Edge(vertices_[5], vertices_[2]));
    faces_.push_back(lateral2);

    // Lateral face 3
    Face lateral3;
    lateral3.push_back(new Edge(vertices_[0], vertices_[2]));
    lateral3.push_back(new Edge(vertices_[2], vertices_[5]));
    lateral3.push_back(new Edge(vertices_[5], vertices_[3]));
    lateral3.push_back(new Edge(vertices_[3], vertices_[0]));
    faces_.push_back(lateral3);
}

bool TriangularPrism::intersect(const Ray &r, double &t, Vector &normal) const
{
    return false;
}

bool TriangularPrism::intersectBasis(const Ray &r, double &t, Vector &normal) const
{
    Triangle t1(vertices_[0], vertices_[1], vertices_[2]);
    Triangle t2(vertices_[3], vertices_[4], vertices_[5]);
    double temp_t1, temp_t2;
    Vector temp_normal1, temp_normal2;
    bool hit = false;

    if( t1.intersect(r, temp_t1, temp_normal1) ) {
        hit = true;
    }
    if( t2.intersect(r, temp_t2, temp_normal2) ) {
        hit = true;
    }

    if( hit ) {
        if( temp_t1 < temp_t2) {
            t = temp_t1;
            normal = temp_normal1;
        } else {
            t = temp_t2;
            normal = temp_normal2;
        }
    }

    return hit;
}

bool TriangularPrism::intersectFaces(const Ray &r, double &t, Vector &normal) const
{
    return false;
}

void TriangularPrism::openGlRender() const
{
    static double angle = 0.0;
    std::vector<Face>::const_iterator it;

    glPushMatrix();
    glLoadIdentity();
    glTranslated(0.0, 0.0, -20.0);
    glRotated(angle, 0.0, 1.0, 0.0);
    glScaled(10.0, 10.0, 10.0);
    glColor3f(1.0, 1.0, 1.0);
    for(it = faces_.begin() ; it != faces_.end() ; it++) {
        const Face &f = *it;
        glBegin(GL_POLYGON);
            for(unsigned int j = 0 ; j < f.size() ; j++) {
                glVertex3dv(f[j]->first->toCArray());
            }
        glEnd();
    }
    glPopMatrix();
    angle += 0.1;
    if( angle >= 360.0 ) {
        angle = angle - 360.0;
    }
}
ICgObject* TriangularPrism::clone() const
{
    TriangularPrism *c = new TriangularPrism();
    c->multiplyCurrentTransformation(this->transformation_);
    c->material_ = this->material_;
    return c;
}
